package colorChanger;

import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.awt.image.MemoryImageSource;
import java.awt.image.PixelGrabber;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;

public class QRCode {
	private Image image;
	private int[] pixels;
	private int[][] pixelsMatrix;
	private int width;
	private int height;
	private int pixelsNumber;
	private double greaterCyan;
	private double lowerCyan;
	private double greaterMagenta;
	private double lowerMagenta;
	private double greaterYellow;
	private double lowerYellow;
	private double greaterKey;
	private double lowerKey;

	public QRCode(String imagePath) throws FileNotFoundException, IOException {
		setImage(imagePathToImage(imagePath));
		setPixels(imageToPixels(getImage()));
		getMaxAndMinPixelColor(getPixels());
		setWidth(getImage().getWidth(null));
		setHeight(getImage().getHeight(null));
		setPixelsMatrix();
		// paintPixelDownNeighborhood();
		matrixToArray();
		// setPixelsMatrix();

	}

	private void getMaxAndMinPixelColor(int[] pixels) {
		CMYK cmyk;
		greaterCyan = RGBtoCMYK.convert(pixels[0]).getC()
				.getIniticalColorIntensity();
		lowerCyan = RGBtoCMYK.convert(pixels[0]).getC()
				.getIniticalColorIntensity();
		greaterMagenta = RGBtoCMYK.convert(pixels[0]).getM()
				.getIniticalColorIntensity();
		lowerMagenta = RGBtoCMYK.convert(pixels[0]).getM()
				.getIniticalColorIntensity();
		greaterYellow = RGBtoCMYK.convert(pixels[0]).getY()
				.getIniticalColorIntensity();
		lowerYellow = RGBtoCMYK.convert(pixels[0]).getY()
				.getIniticalColorIntensity();
		greaterKey = RGBtoCMYK.convert(pixels[0]).getK()
				.getIniticalColorIntensity();
		lowerKey = RGBtoCMYK.convert(pixels[0]).getK()
				.getIniticalColorIntensity();

		for (int i = 0; i < pixels.length; i++) {
			cmyk = RGBtoCMYK.convert(pixels[i]);
			double cyan = cmyk.getC().getIniticalColorIntensity();
			double magenta = cmyk.getM().getIniticalColorIntensity();
			double yellow = cmyk.getY().getIniticalColorIntensity();
			double key = cmyk.getK().getIniticalColorIntensity();

			if (cyan > greaterCyan) {
				greaterCyan = cyan;
			}
			if (cyan < lowerCyan) {
				lowerCyan = cyan;
			}
			if (magenta > greaterMagenta) {
				greaterMagenta = magenta;
			}
			if (magenta < lowerMagenta) {
				lowerMagenta = magenta;
			}
			if (yellow > greaterYellow) {
				greaterYellow = yellow;
			}
			if (yellow < lowerYellow) {
				lowerYellow = yellow;
			}
			if (key > greaterKey) {
				greaterKey = key;
			}
			if (key < lowerKey) {
				lowerKey = key;
			}
		}

	}

	public int getPixelsNumber() {
		return pixelsNumber;
	}

	public void setPixelsNumber(int pixelsNumber) {
		this.pixelsNumber = pixelsNumber;
	}

	public double getGreaterCyan() {
		return greaterCyan;
	}

	public void setGreaterCyan(double greaterCyan) {
		this.greaterCyan = greaterCyan;
	}

	public double getLowerCyan() {
		return lowerCyan;
	}

	public void setLowerCyan(double lowerCyan) {
		this.lowerCyan = lowerCyan;
	}

	public double getGreaterMagenta() {
		return greaterMagenta;
	}

	public void setGreaterMagenta(double greaterMagenta) {
		this.greaterMagenta = greaterMagenta;
	}

	public double getLowerMagenta() {
		return lowerMagenta;
	}

	public void setLowerMagenta(double lowerMagenta) {
		this.lowerMagenta = lowerMagenta;
	}

	public double getGreaterYellow() {
		return greaterYellow;
	}

	public void setGreaterYellow(double greaterYellow) {
		this.greaterYellow = greaterYellow;
	}

	public double getLowerYellow() {
		return lowerYellow;
	}

	public void setLowerYellow(double lowerYellow) {
		this.lowerYellow = lowerYellow;
	}

	public void setPixelsMatrix(int[][] pixelsMatrix) {
		this.pixelsMatrix = pixelsMatrix;
	}

	private void paintPixelDownNeighborhood() {
		for (int i = 0; i < getHeight() - 2; i++) {
			for (int j = 0; j < getWidth() - 1; j++) {

				if (i + 1 < getHeight() - 1 && i - 1 > 0 && j - 1 > 0
						&& j + 1 < getWidth() - 1) {
					// System.out.println("i " + i + " j " + j);
					// if (getPixelsMatrix()[j + 1][i] == getPixelsMatrix()[j +
					// 1][i + 1]
					// && getPixelsMatrix()[j + 1][i + 1] == getPixelsMatrix()[j
					// + 1][i - 1]) {
					getPixelsMatrix()[j][i] = RGBtoCMYK.YELLOW_PIXEL;
					// System.out.println("pintou");
					// }
				}
			}
		}
	}

	public void writhImage(String fileName) {
		BufferedImage bufferedImage = new BufferedImage(getWidth(),
				getHeight(), BufferedImage.TYPE_INT_RGB);
		Graphics2D g2 = bufferedImage.createGraphics();
		g2.drawImage(getImageFromPixelArray(), null, null);
		File imageFile = new File(fileName + ".png");
		try {
			ImageIO.write(bufferedImage, "png", imageFile);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public Image getImageFromPixelArray() {
		MemoryImageSource mis = new MemoryImageSource(getWidth(), getHeight(),
				getPixels(), 0, getWidth());
		Toolkit tk = Toolkit.getDefaultToolkit();
		return tk.createImage(mis);
	}

	private Image imagePathToImage(String filePath)
			throws FileNotFoundException, IOException {
		File file = new File(filePath);

		FileInputStream fis = new FileInputStream(file);
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		byte[] buf = new byte[1024];

		for (int readNum; (readNum = fis.read(buf)) != -1;) {
			bos.write(buf, 0, readNum);
		}
		byte[] bytes = bos.toByteArray();

		return new ImageIcon(bytes).getImage();
	}

	private int[] imageToPixels(Image image) {

		width = image.getWidth(null);
		height = image.getHeight(null);
		pixelsNumber = width * height;
		pixels = new int[pixelsNumber];

		PixelGrabber pg = new PixelGrabber(image, 0, 0, width, height, pixels,
				0, width);

		try {
			pg.grabPixels();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		for (int i = 0; i < pixels.length; i++) {
//			 pixels[i] = RGBtoCMYK.convertAbsoluteValue(pixels[i]);
			// TODO
		}
		return pixels;
	}

	public Image getImage() {

		return image;

	}

	public void setImage(Image image) {
		this.image = image;
	}

	public int[] getPixels() {
		return pixels;
	}

	public void setPixels(int[] pixels) {
		this.pixels = pixels;
	}

	public int getWidth() {
		return width;
	}

	public void setWidth(int width) {
		this.width = width;
	}

	public int getHeight() {
		return height;
	}

	public void setHeight(int height) {
		this.height = height;
	}

	public int[][] getPixelsMatrix() {
		return pixelsMatrix;
	}

	public void setPixelsMatrix() {
		pixelsMatrix = new int[getWidth()][getHeight()];
		int pixelIndex = 0;
		for (int i = 0; i < getHeight(); i++) {
			for (int j = 0; j < getWidth(); j++) {
				pixelsMatrix[j][i] = getPixels()[pixelIndex];
				pixelIndex++;
			}
		}
	}

	public void matrixToArray() {
		int pixelIndex = 0;
		for (int i = 0; i < getHeight(); i++) {
			for (int j = 0; j < getWidth(); j++) {
				getPixels()[pixelIndex] = pixelsMatrix[j][i];
				pixelIndex++;
			}
		}
	}

	public double getLowerKey() {
		return lowerKey;
	}

	public void setLowerKey(double lowerKey) {
		this.lowerKey = lowerKey;
	}
	public double getGreaterKey() {
		return greaterKey;
	}

	public void setGreaterKey(double greaterKey) {
		this.greaterKey = greaterKey;
	}
}
